from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.exceptions import ValidationError
from django.utils import timezone
from datetime import timedelta


class Department(models.Model):
    """部门模型"""
    name = models.CharField('部门名称', max_length=100)
    description = models.TextField('部门描述', blank=True)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    
    class Meta:
        verbose_name = '部门'
        verbose_name_plural = '部门'
    
    def __str__(self):
        return self.name


class UserProfile(models.Model):
    """用户配置文件"""
    ROLE_CHOICES = [
        ('employee', '员工'),
        ('supervisor', '主管'),
        ('hr', '人事'),
        ('admin', '管理员'),
    ]
    
    user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='用户')
    employee_id = models.CharField('工号', max_length=20, unique=True)
    department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, verbose_name='部门')
    position = models.CharField('职位', max_length=100)
    role = models.CharField('角色', max_length=20, choices=ROLE_CHOICES, default='employee')
    supervisor = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='直属上级')
    phone = models.CharField('电话', max_length=20, blank=True)
    hire_date = models.DateField('入职日期', null=True, blank=True)
    annual_leave_days = models.IntegerField('年假天数', default=5)
    used_leave_days = models.IntegerField('已用年假天数', default=0)
    
    class Meta:
        verbose_name = '用户配置'
        verbose_name_plural = '用户配置'
    
    def __str__(self):
        return f"{self.user.get_full_name() or self.user.username} ({self.employee_id})"
    
    @property
    def remaining_leave_days(self):
        """剩余年假天数"""
        return self.annual_leave_days - self.used_leave_days
    
    def can_approve_leave(self):
        """是否可以审批请假"""
        return self.role in ['supervisor', 'hr', 'admin']


class LeaveType(models.Model):
    """请假类型"""
    name = models.CharField('请假类型', max_length=50, unique=True)
    description = models.TextField('描述', blank=True)
    max_days = models.IntegerField('最大天数', default=30, help_text='单次申请最大天数')
    requires_attachment = models.BooleanField('需要附件', default=False)
    is_active = models.BooleanField('是否启用', default=True)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    
    class Meta:
        verbose_name = '请假类型'
        verbose_name_plural = '请假类型'
    
    def __str__(self):
        return self.name


class LeaveApplication(models.Model):
    """请假申请"""
    STATUS_CHOICES = [
        ('draft', '草稿'),
        ('submitted', '已提交'),
        ('supervisor_approved', '主管已批准'),
        ('hr_approved', '人事已批准'),
        ('approved', '已批准'),
        ('rejected', '已拒绝'),
        ('cancelled', '已取消'),
    ]
    
    applicant = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='申请人')
    leave_type = models.ForeignKey(LeaveType, on_delete=models.CASCADE, verbose_name='请假类型')
    start_date = models.DateField('开始日期', help_text='请选择开始日期')
    end_date = models.DateField('结束日期')
    days_requested = models.IntegerField('请假天数', editable=False)
    reason = models.TextField('请假原因')
    attachment = models.FileField('附件', upload_to='leave_attachments/', blank=True, null=True)
    status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='draft')
    # emergency_contact = models.CharField('紧急联系人', max_length=100, blank=True)
    emergency_contact = models.ForeignKey(UserProfile, on_delete=models.CASCADE, blank=True, null=True)
    emergency_phone = models.CharField('紧急联系电话', max_length=20, blank=True)
    work_handover = models.TextField('工作交接', blank=True, help_text='请说明工作交接安排')
    
    # 审批相关字段
    supervisor_approver = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, blank=True,
        related_name='supervised_leaves', verbose_name='主管审批人'
    )
    hr_approver = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, blank=True,
        related_name='hr_approved_leaves', verbose_name='人事审批人'
    )
    
    # 时间戳
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)
    submitted_at = models.DateTimeField('提交时间', null=True, blank=True)
    approved_at = models.DateTimeField('批准时间', null=True, blank=True)
    
    class Meta:
        verbose_name = '请假申请'
        verbose_name_plural = '请假申请'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.applicant.get_full_name() or self.applicant.username} - {self.leave_type.name} ({self.start_date} 至 {self.end_date})"
    
    def clean(self):
        """数据验证"""
        if self.start_date and self.end_date:
            if self.start_date > self.end_date:
                raise ValidationError('开始日期不能晚于结束日期')
            
            if self.start_date < timezone.now().date():
                raise ValidationError('开始日期不能早于今天')
            
            # 计算请假天数（排除周末）
            days = self.calculate_business_days()
            if days > self.leave_type.max_days:
                raise ValidationError(f'请假天数不能超过{self.leave_type.max_days}天')
    
    def save(self, *args, **kwargs):
        # 自动计算请假天数
        if self.start_date and self.end_date:
            self.days_requested = self.calculate_business_days()
        
        # 设置提交时间
        if self.status == 'submitted' and not self.submitted_at:
            self.submitted_at = timezone.now()
        
        # 设置批准时间
        if self.status == 'approved' and not self.approved_at:
            self.approved_at = timezone.now()
        
        super().save(*args, **kwargs)
    
    def calculate_business_days(self):
        """计算工作日天数（排除周末）"""
        if not self.start_date or not self.end_date:
            return 0
        
        current_date = self.start_date
        business_days = 0
        
        while current_date <= self.end_date:
            # 0=Monday, 6=Sunday
            if current_date.weekday() < 5:  # Monday to Friday
                business_days += 1
            current_date += timedelta(days=1)
        
        return business_days
    
    def can_be_cancelled(self):
        """是否可以取消"""
        return self.status in ['draft', 'submitted'] and self.start_date > timezone.now().date()
    
    def can_be_edited(self):
        """是否可以编辑"""
        return self.status == 'draft'
    
    def get_next_approver(self):
        """获取下一个审批人"""
        if self.status == 'submitted':
            # 需要主管审批
            return self.applicant.userprofile.supervisor.user if self.applicant.userprofile.supervisor else None
        elif self.status == 'supervisor_approved':
            # 需要人事审批（超过3天的请假）
            if self.days_requested > 3:
                from django.contrib.auth.models import User
                hr_users = User.objects.filter(userprofile__role='hr', is_active=True)
                return hr_users.first() if hr_users.exists() else None
        return None


class ApprovalRecord(models.Model):
    """审批记录"""
    ACTION_CHOICES = [
        ('submit', '提交申请'),
        ('approve', '批准'),
        ('reject', '拒绝'),
        ('cancel', '取消'),
        ('return', '退回'),
    ]
    
    leave_application = models.ForeignKey(
        LeaveApplication, on_delete=models.CASCADE,
        related_name='approval_records', verbose_name='请假申请'
    )
    approver = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='操作人')
    action = models.CharField('操作', max_length=20, choices=ACTION_CHOICES)
    comments = models.TextField('备注', blank=True)
    created_at = models.DateTimeField('操作时间', auto_now_add=True)
    
    class Meta:
        verbose_name = '审批记录'
        verbose_name_plural = '审批记录'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.approver.get_full_name() or self.approver.username} - {self.get_action_display()}"


class LeaveBalance(models.Model):
    """请假余额"""
    user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
    leave_type = models.ForeignKey(LeaveType, on_delete=models.CASCADE, verbose_name='请假类型')
    year = models.IntegerField('年份', default=timezone.now().year)
    total_days = models.IntegerField('总天数', default=0)
    used_days = models.IntegerField('已用天数', default=0)
    
    class Meta:
        verbose_name = '请假余额'
        verbose_name_plural = '请假余额'
        unique_together = ['user', 'leave_type', 'year']
    
    def __str__(self):
        return f"{self.user.get_full_name() or self.user.username} - {self.leave_type.name} ({self.year})"
    
    @property
    def remaining_days(self):
        """剩余天数"""
        return self.total_days - self.used_days


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    """用户创建时自动创建配置文件"""
    if created:
        UserProfile.objects.create(
            user=instance,
            employee_id=f"EMP{instance.id:04d}",
            position="员工",
            hire_date="2024-01-01"
        )


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    """保存用户时同时保存配置文件"""
    if hasattr(instance, 'userprofile'):
        instance.userprofile.save()


@receiver(post_save, sender=LeaveApplication)
def handle_leave_application_status_change(sender, instance, created, **kwargs):
    """处理请假申请状态变更"""
    if not created:
        # 如果状态变为已批准，更新用户的已用假期天数
        if instance.status == 'approved' and instance.leave_type.name == '年假':
            profile = instance.applicant.userprofile
            profile.used_leave_days += instance.days_requested
            profile.save()
